﻿using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;

namespace housingsafety.server.Helpers
{
    public class DiskFileStoreHelper
    {
        private const string BackupWorkFolder = ".dbackup";
        private const string BackupWorkTimePointFile = "timept";
        private const string BackupWorkTimePointLockFile = "timept.lock";
        private const string TimeFormat = "yyyyMMdd HH:mm:ss";

        /// <summary>
        /// 获取需要备份的文件
        /// </summary>
        /// <param name="diskFileRootFolder"></param>
        /// <param name="dt"></param>
        /// <param name="bakfs"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        public static BackupTrans GetBackupFiles(string diskFileRootFolder, DateTime dt
            , System.Collections.Generic.Dictionary<string, string> bakfs, StringBuilder errors)
        {
            var backupRoot = Path.Combine(diskFileRootFolder, BackupWorkFolder);
            Directory.CreateDirectory(backupRoot);
            var timePoint = Path.Combine(backupRoot, BackupWorkTimePointFile);
            var timePointLock = Path.Combine(backupRoot, BackupWorkTimePointLockFile);

            var proc = Process.GetCurrentProcess();
            string transId = $"{proc.Id}:{Guid.NewGuid():N}";
            File.WriteAllText(timePointLock, transId);

            DateTime dtStart = DateTime.MinValue;
            if (File.Exists(timePoint) && new FileInfo(timePoint).Length > 0)
            {
                var allText = File.ReadAllText(timePoint);
                DateTime.TryParseExact(allText, TimeFormat, System.Globalization.CultureInfo.InvariantCulture,
                                   System.Globalization.DateTimeStyles.None, out dtStart);
            }

            var monthStartFolder = $"{dtStart.Year:D4}{dtStart.Month:D2}";
            var dayStartFolder = $"{monthStartFolder}{dtStart.Month:D2}{dtStart.Day:D2}";

            var monthNowFolder = $"{dt.Year:D4}{dt.Month:D2}";
            var dayNowFolder = $"{monthNowFolder}{dt.Month:D2}{dt.Day:D2}";

            var monthFolder = Directory.GetDirectories(diskFileRootFolder)
                .Where(_ =>
                {
                    var name = Path.GetFileName(_);
                    return !name.Equals(BackupWorkFolder)
                && name.Length == monthNowFolder.Length
                && name.CompareTo(monthStartFolder) >= 0
                && name.CompareTo(monthNowFolder) <= 0;
                });

            foreach (var mf in monthFolder)
            {
                var pName = Path.GetFileName(mf);
                var dayFolders = Directory.GetDirectories(mf)
                .Where(_ =>
                {
                    string name = $"{pName}{Path.GetFileName(_)}";
                    return name.Length == dayNowFolder.Length
                   && name.CompareTo(dayStartFolder) >= 0
                   && name.CompareTo(dayNowFolder) < 0;
                }
                );

                foreach (var item in dayFolders)
                {
                    foreach (var f in Directory.GetFiles(item))
                    {
                        string key = f.Substring(diskFileRootFolder.Length + 1);
                        bakfs.Add(key, f);
                    }
                }
            }

            return new BackupTrans(backupRoot, transId, dt);
        }

        internal static bool SuccBackupFiles(BackupTrans backupTrans, StringBuilder errors)
        {
            if (null == backupTrans)
            {
                errors.Append("backupTrans is null");
                return false;
            }

            var timePoint = Path.Combine(backupTrans.BackupRoot, BackupWorkTimePointFile);
            var timePointLock = Path.Combine(backupTrans.BackupRoot, BackupWorkTimePointLockFile);
            if (!File.Exists(timePointLock) || new FileInfo(timePointLock).Length < 1)
            {
                errors.Append(".lock file is null or empty");
                return false;
            }

            var allText = File.ReadAllText(timePointLock);
            if (!string.Equals(backupTrans.TransId.Trim(), allText.Trim()))
            {
                errors.Append("transId is not match");
                return false;
            }

            File.WriteAllText(timePoint, backupTrans.Dt.ToString(TimeFormat));
            File.Delete(timePointLock);
            return true;
        }

        public static string FinalFileName(DateTime dt, string id, string objectName)
        {
            string uniqueFileName = $"{id}_{objectName}";
            return uniqueFileName;
        }

        public static StorePath EnsureStoreFolder(string baseFolder, DateTime dt, string userName, string groupName)
        {
            var relativelyFolder = $"{userName}/{groupName}";
            string storeFolder = Path.Combine(baseFolder, relativelyFolder);
            if (!Directory.Exists(storeFolder))
            {
                Directory.CreateDirectory(storeFolder);
            }

            return new StorePath()
            {
                FullFolder = storeFolder,
                BaseFolder = baseFolder,
                RelativelyFolder = relativelyFolder
            };
        }
    }
}
